<?php

namespace app\api\logic;


use app\api\cache\KeysUtil;
use app\api\cache\Marketing;
use app\api\cache\MemberCache;
use app\api\cache\RedisCache;
use app\api\consDir\ErrorConst;
use app\api\services\CardService;
use app\api\services\MemberService;
use app\api\services\PayService;
use app\api\services\RabbitMqService;
use app\api\services\ServiceCenterService;
use app\common\libs\Singleton;
use app\common\models\Card\Card;
use app\common\models\Card\CardOrder;
use app\common\models\Card\CardUser;
use app\common\models\Card\CardUserItem;
use app\common\models\Card\CardUserItemLog;
use app\common\models\Service\Service;
use app\common\utils\CommonUtil;
use app\common\utils\RedLock;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\facade\Log;

/**
 * 订单模块
 * Class MemberLogic
 * @package app\api\logic
 */
class CardLogic extends BaseLogic
{
    use Singleton;


    /**
     * @throws DataNotFoundException
     * @throws ModelNotFoundException
     * @throws DbException
     */
    public function cardList(): array
    {
        $cardTimeType = CardUser::getInstance()->where('user_id',$this->userinfo->id)->order('card_time_type desc')->value('card_time_type');
        $where = [
            ['deleted', '=', 0],
            ['status', '=', 1],
        ];
        if($cardTimeType){
            $where[] = ['time_type','>=',$cardTimeType];
        }
        $logList = Card::getInstance()
            ->where($where)
            ->order('sort desc,id desc')
            ->select();
        return empty($logList) ? [] : $logList->toArray();
    }

    /**
     * @throws ModelNotFoundException
     * @throws DataNotFoundException
     * @throws DbException
     */
    public function orderList($status, $page, $pageSize): array
    {
        $list = CardService::getInstance()->orderList($this->userinfo->id, $status, $page, $pageSize);
        return ['rows' => $list];
    }

    /**
     * @throws ModelNotFoundException
     * @throws DataNotFoundException
     * @throws DbException
     */
    public function createOrder($cardId): array
    {
        if (empty($cardId)) {
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, ErrorConst::PARAM_ERROR_MSG);
        }
        $where = [
            ['id', '=', $cardId],
            ['deleted', '=', 0],
        ];
        $card = Card::getInstance()->where($where)->find();
        if (empty($card)) {
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, '会员卡不存在');
        }
        if ($card['status'] == 0) {
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, '该会员卡已停售');
        }
        if ($card['price'] <= 0) {
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, '价格异常');
        }
        $cardUser = CardUser::getInstance()->where('user_id',$this->userinfo->id)->order('card_time_type desc')->find();
        if($cardUser){
            if($card['timeType'] < $cardUser['cardTimeType']){
                CommonUtil::throwException(ErrorConst::PARAM_ERROR, '不能降级购买会员卡');
            }
        }

        $orderNo = getNo('CD');
        $order = CardService::getInstance()->createOrder($this->userinfo->id, $card, $orderNo);
        if (!$order) {
            CommonUtil::throwException(ErrorConst::SYSTEM_ERROR, ErrorConst::SYSTEM_ERROR_MSG);
        }

        $expireAt = date('Y-m-d H:i:s', strtotime('+5 minutes'));
        return ['orderNo' => $orderNo, 'expireAt' => $expireAt,'payPrice' => $card['price']];
    }

    /**
     * @throws DataNotFoundException
     * @throws ModelNotFoundException
     * @throws DbException
     */
    public function payOrder($orderNo, $payType, $payPassword, $paySubType): array
    {
        if ( ! RedLock::getInstance()->lock('cardPayOrder_' . $this->userinfo->id, 3)) {
            CommonUtil::throwException(ErrorConst::FREQUENT_ERROR, ErrorConst::FREQUENT_ERROR_MSG);
        }

        if ($payType == 3) {
            $account = MemberService::getInstance()->account($this->userinfo->id);
            if (empty($account)) {
                CommonUtil::throwException(ErrorConst::NO_PAY_PASSWORD_ERROR, ErrorConst::NO_PAY_PASSWORD_ERROR_MSG);
            }

            //验证支付密码
            if ($account['payPwd'] != $payPassword) {
                CommonUtil::throwException(ErrorConst::PAY_PASSWORD_ERROR, ErrorConst::PAY_PASSWORD_ERROR_MSG);
            }
        }

        $order = CardService::getInstance()->getOrderInfo($orderNo, $this->userinfo->id);
        if (empty($order)) {
            CommonUtil::throwException(ErrorConst::NO_ORDER_ERROR, ErrorConst::NO_ORDER_ERROR_MSG);
        }
        if ($order['status'] != 0) {
            CommonUtil::throwException(ErrorConst::ORDER_STATUS_ERROR, ErrorConst::ORDER_STATUS_ERROR_MSG);
        }

        $where = [
            ['deleted','=',0],
            ['id','=',$order['cardId']]
        ];
        $card = Card::getInstance()->where($where)->find();
        if(empty($card)){
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, '会员卡不存在');
        }
        if($card['status'] == 0){
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, '会员卡已停售');
        }
        if($card['stock'] <= 0){
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, '库存不足');
        }

        $cardUser = CardUser::getInstance()->where('user_id',$this->userinfo->id)->order('card_time_type desc')->find();
        if($cardUser){
            if($card['timeType'] < $cardUser['cardTimeType']){
                CommonUtil::throwException(ErrorConst::PARAM_ERROR, '不能降级购买会员卡');
            }
        }

        $isBalance = 0;

        CardOrder::getInstance()->where('order_no', $orderNo)->update([
            'pay_type' => $payType,
        ]);
        $payInfo = PayService::getInstance()->payOrder($this->userinfo->id, $order, $payType);
        if ($payType == 3) {
            $userBalance = MemberService::getInstance()->finance($this->userinfo->id);
            if ($payInfo['pay_price'] > $userBalance['amount']) {
                CommonUtil::throwException(ErrorConst::ORDER_STATUS_ERROR, '余额不足');
            }
            $isBalance = 1;
        }

        $userInfo = MemberService::getInstance()->getUserInfo($this->userinfo->id);
        if ($payType == 3) {
            //余额全付
            $info = [
                'pay_status' => 3,
                'pay_no' => $payInfo['pay_no'],
                'money' => $payInfo['pay_price'],
                'trade_no' => '',
                'receipt_data' => '',
            ];
            $event["exchange"] = config('rabbitmq.order_callback_queue');
            RabbitMqService::send($event, $info);
            $pay = [];
        } elseif ($payType == 4) {
            $pay = SandLogic::getInstance()->orderCreate($this->userinfo->id, $payInfo['pay_price'], $payInfo['pay_no']);
        } elseif ($payType == 5) {
            $pay = SandLogic::getInstance()->orderCreateScan($payInfo['pay_price'], $payInfo['pay_no']);
        } else {
            $pay = PayService::getInstance()->toPay($payInfo, $userInfo, $payType, $paySubType);
        }
        return ['payInfo' => $pay, 'isBalance' => $isBalance];
    }

    /**
     * @throws ModelNotFoundException
     * @throws DataNotFoundException
     * @throws DbException
     */
    public function orderDetail($orderNo): array
    {
        if(empty($orderNo)){
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, '订单号不能为空');
        }
        $order = CardService::getInstance()->getOrderInfo($orderNo,$this->userinfo->id);
        if($order){
            //客服电话
            $order['tel'] = '18938533289';
        }
        $cardUser = CardUser::getInstance()->where('card_id',$order['cardId'])->where('user_id',$this->userinfo->id)->find();
        $order['card_user'] = !empty($cardUser) ? $cardUser->toArray() : [];
        return $order;
    }

    public function cancelOrder($orderNo): bool
    {
        if ( ! RedLock::getInstance()->lock('cardCancelOrder_' . $this->userinfo->id, 3)) {
            CommonUtil::throwException(ErrorConst::FREQUENT_ERROR, ErrorConst::FREQUENT_ERROR_MSG);
        }
        if(empty($orderNo)){
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, '订单号不能为空');
        }
        $where = [
            ['order_no','=',$orderNo],
            ['status','=',0]
        ];
        CardOrder::getInstance()->where($where)->update(['update_at' => date('Y-m-d H:i:s'),'status' => 2]);
        return true;
    }

    /**
     * @throws ModelNotFoundException
     * @throws DataNotFoundException
     * @throws DbException
     */
    public function cardUser(): array
    {
        $where = [
            ['user_id','=',$this->userinfo->id],
            ['status','=',1],
        ];
        $cardUser = CardUser::getInstance()->where($where)->order('card_time_type desc')->find();
        if(empty($cardUser)){
            return [];
        }
        $isEnd = 1;
        if(date('Y-m-d H:i:s') > $cardUser['expireAt']){
            $isEnd = 0;
        }
        $cardUser->isEnd = $isEnd;
        return $cardUser->toArray();
    }

    /**
     * @throws DataNotFoundException
     * @throws ModelNotFoundException
     * @throws DbException
     */
    public function cardItem($orderNo): array
    {
        if(empty($orderNo)){
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, '订单号不能为空');
        }
        $where = [
            ['user_id','=',$this->userinfo->id],
            ['order_no','=',$orderNo],
        ];
        $count = CardUserItem::getInstance()->where($where)->count();
        //不存在核销码 生成
        if($count < 1){
            $where = [
                ['order_no','=',$orderNo],
                ['user_id','=',$this->userinfo->id],
                ['status','=',1]
            ];
            $order = CardOrder::getInstance()->where($where)->find();
            if(empty($order)){
                CommonUtil::throwException(ErrorConst::PARAM_ERROR, '订单不存在');
            }
            $card = Card::getInstance()->where('id',$order['cardId'])->find();
            if(empty($card)){
                CommonUtil::throwException(ErrorConst::PARAM_ERROR, '会员卡类型不存在');
            }
            if($card['serviceContent']){
                $itemArr = json_decode($card['serviceContent'],1);
                $insertData = [];
                foreach($itemArr as $v){
                    $insertData[] = [
                        'user_id' => $this->userinfo->id,
                        'order_no' => $orderNo,
                        'code' => getNo('1'),
                        'card_type' => $card['type'],
                        'card_id' => $card['id'],
                        'title' => $v['title'],
                        'total_num' => $v['num'],
                        'num' => $v['num'],
                        'price' => $v['price'],
                        'content' => $v['content'],
                        'remark' => $card['remark'],
                        'image' => $v['image']
                    ];
                }
                CardUserItem::getInstance()->insertAll($insertData);
            }
        }

        $list = CardUserItem::getInstance()->where('order_no',$orderNo)->select();
        return !empty($list) ? $list->toArray() : [];
    }

    /**
     * @throws ModelNotFoundException
     * @throws DataNotFoundException
     * @throws DbException
     */
    public function cardUserItemLog($orderNo): array
    {
        $where = [
            ['user_id','=',$this->userinfo->id]
        ];
        if(!empty($orderNo)){
            $where[] = ['order_no','like','%'.$orderNo.'%'];
        }
        $list = CardUserItemLog::getInstance()->where($where)->order('id desc')->select();
        foreach($list as &$v){
            $v['address'] = $v['service_province'].$v['service_city'].$v['service_country'].$v['service_street'].$v['service_comm'].$v['detailAddress'];
            $v['userName'] = MemberCache::getInfo($v['userId'],'user_name');
            $v['checkUserName'] = MemberCache::getInfo($v['checkUserId'],'user_name');
        }
        return !empty($list) ? $list->toArray() : [];
    }

    public function cardUse($code,$serviceId): bool
    {
        if(empty($code)){
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, '核销码不能为空');
        }
        if(empty($serviceId)){
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, 'serviceId不能为空');
        }
        $where = [
            //['user_id','=',$this->userinfo->id],
            ['deleted','=',0],
            ['id','=',$serviceId]
        ];
        $service = Service::getInstance()->where($where)->find();
        if(empty($service)){
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, '服务中心不存在');
        }
        if($service['status'] == 1){
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, '服务中心已停业');
        }
        $where = [
            ['code','=',$code],
        ];
        $cardUserItem = CardUserItem::getInstance()->where($where)->find();
        if(empty($cardUserItem)){
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, '服务项目不存在');
        }
        if($cardUserItem['num'] < 1){
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, '服务次数不足');
        }
        $where = [
            ['user_id','=',$cardUserItem['userId']],
            ['card_id','=',$cardUserItem['cardId']],
        ];
        $cardUser = CardUser::getInstance()->where($where)->find();
        if(empty($cardUser)){
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, '会员卡不存在');
        }
        if($cardUser['expire_at'] < date('Y-m-d H:i:s')){
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, '会员卡已过期');
        }
        $orderNo = CardUserItem::getInstance()->where('code',$code)->value('order_no');
        $order = CardOrder::getInstance()->where('order_no',$orderNo)->find();
        CardUserItemLog::getInstance()->startTrans();
        try{
            $cardUserItem->num--;
            $cardUserItem->save();
            $data = [
                'user_id' => $cardUserItem['userId'],
                'item_code' => $code,
                'order_no' => $cardUserItem['orderNo'],
                'title' => $cardUserItem['title'],
                'check_user_id' => $this->userinfo->id,
                'image' => $cardUserItem['image'],
                'service_province' => $service['service_province'],
                'service_province_id' => $service['service_province_id'],
                'service_city' => $service['service_city'],
                'service_city_id' => $service['service_city_id'],
                'service_country' => $service['service_country'],
                'service_country_id' => $service['service_country_id'],
                'service_street' => $service['service_street'],
                'service_street_id' => $service['service_street_id'],
                'service_comm' => $service['service_comm'],
                'service_comm_id' => $service['service_comm_id'],
                'detail_address' => $service['detail_address'],
            ];
            CardUserItemLog::getInstance()->insert($data);
            $service = Service::getInstance()->where('id',$service['id'])->find();
            if($order['payPrice'] > 0){
                $standardConfig = Marketing::getKeyData('card', 'standard');
                $specialConfig = Marketing::getKeyData('card', 'special');
                    //card_type 卡类型 0标准卡 1特殊卡
                $rate = 0;
                if($cardUserItem->card_type == 0){
                    if ($standardConfig['status'] == 1) {
                        $rate = $standardConfig['direct_used_rate'];
                    }
                }else{
                    if ($standardConfig['status'] == 1) {
                        $rate = $specialConfig['direct_used_rate'];
                    }
                }
                if($rate > 0){
                    $bonus = bcmul($order['payPrice'], $rate * 0.01, 4);
                    ServiceCenterService::getInstance()->changeService($serviceId,'card_add',$bonus,'会员卡核销收入',$cardUserItem['orderNo']);
                }
            }
        }catch (\Exception $e){
            CardUserItemLog::getInstance()->rollback();
            CommonUtil::throwException(ErrorConst::PARAM_ERROR, $e->getMessage());
        }
        CardUserItemLog::getInstance()->commit();
        return true;
    }

    /**
     * @throws ModelNotFoundException
     * @throws DataNotFoundException
     * @throws DbException
     */
    public function cardItemDetail($code): array
    {
        $detail = CardUserItem::getInstance()->field('title,image,num')->where('code',$code)->find();
        return   !empty($detail) ? $detail->toArray() : [];
    }
}
